package com.yintw.com.yintw.aspect.admin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yintw.com.yintw.aspect.admin.annotation.MultiMethod;
import com.yintw.com.yintw.aspect.admin.annotation.OriginalControllerReturnValue;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.UUID;

@Aspect
@Service
@Slf4j
public class TestAspect {

    public TestAspect() {
    }

    @Pointcut("@annotation(com.yintw.com.yintw.aspect.admin.annotation.MultiMethod)")
    public void multiMethodPointCut() {

    }

    @Pointcut("@annotation(com.yintw.com.yintw.aspect.admin.annotation.OriginalControllerReturnValue)")
    public void originalControllerReturnValuePointCut() {

    }

    @Around(value = "multiMethodPointCut() || originalControllerReturnValuePointCut()")
    public Object aroundMQAdminMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        //通过uuid关联请求参数和返回参数
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        methodBefore(joinPoint, uuid);
        try {
            Object proceed = joinPoint.proceed();
            methodAfterReturing(proceed, uuid);
        } catch (Exception e) {
            log.error("[{}]Response异常内容:{}", uuid, e);
            throw e;
        }
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        MultiMethod multiMethod = method.getAnnotation(MultiMethod.class);
        OriginalControllerReturnValue originalControllerReturnValue = method.getAnnotation(OriginalControllerReturnValue.class);
        if(multiMethod!=null)
            log.info("anno:[{}] key:[{}]  value:[{}] ","MultiMethod","name",multiMethod.name());
            log.info("anno:[{}] key:[{}]  value:[{}] ","MultiMethod","value",multiMethod.value());
        if(originalControllerReturnValue!=null)
            log.info("anno:[{}] key:[{}]  value:[{}] ","OriginalControllerReturnValue","name",originalControllerReturnValue.name());
            log.info("anno:[{}] key:[{}]  value:[{}] ","OriginalControllerReturnValue","value",originalControllerReturnValue.value());


        return joinPoint.proceed();
    }
    public void methodBefore(JoinPoint joinPoint, String uuid) {
        // 打印请求内容
        try {
            // 下面两个数组中，参数值和参数名的个数和位置是一一对应的。
            Object[] objs = joinPoint.getArgs();
            String argNames = joinPoint.getSignature().getName();
            for(Object obj : objs){
                log.info("\r\n[{}]方法:{}\n名称:{}\n参数:{}", uuid, argNames, joinPoint.getSignature(), JSON.parseObject(obj.toString()).toJSONString());
            }
        } catch (Exception e) {
            log.error("[{}]AOP methodBefore:", uuid, e);
        }
    }

    public void methodAfterReturing(Object o, String uuid) {
        try {
            if (o != null)
                log.info("[{}]Response内容:{}", uuid, JSONObject.toJSON(o));
        } catch (Exception e) {
            log.error("[{}]AOP methodAfterReturing:", uuid, e);
        }
    }
}
